﻿
/***************************************************************************

Copyright (c) BizRulX. All rights reserved.

***************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.XPath;
using System.Windows.Forms;
using System.Data;
using System.Xml;

namespace RuleXSoft.BizRuleCreator
{
    public class XMLRecordGenerator
    {
        //Dictionary<string, T> objDeserializedXml = null;

        public XMLRecordGenerator()
        {
            //objDeserializedXml = new Dictionary<string, T>();
        }

        public XPathNodeIterator GetXMLNodes(string fileName)
        {
            XPathNodeIterator _xmlNodes;

            XPathDocument document = new XPathDocument(fileName);
            XPathNavigator navigator = document.CreateNavigator();
            XPathNodeIterator nodes = navigator.Select("Types/RuleSetClass/RuleSet/Rule");

            _xmlNodes = nodes;
            
            return _xmlNodes;
        }

        

        public DataTable GenerateData(XPathNodeIterator nodes)
        {

            try
            {
                bool IsCreateColumn = true;
                DataSet dsRulX = new DataSet();
                DataTable dtRulX = new DataTable();
                StringBuilder sbRowValueList = new StringBuilder();

                string strKey = string.Empty;
                string strField = string.Empty;
                string strOperator = string.Empty;
                string strDataType = string.Empty;
                string strOutput = string.Empty;
                string strRuleID = string.Empty;
                string strIsDerived = string.Empty;
                string strIsNullAllowed = string.Empty;

                //DataRow drRulX;
                //drRulX = dtRulX.NewRow();
                dtRulX.Columns.Add(new DataColumn("RuleID"));
                //Make RuleID column readonly
                dtRulX.Columns["RuleID"].ReadOnly = true;

                DataRow drDataTypeRulX;
                drDataTypeRulX = dtRulX.NewRow();

                while (nodes.MoveNext())
                {
                    DataRow drRulX;
                    drRulX = dtRulX.NewRow();
                    strField = nodes.Current.GetAttribute("ID", string.Empty);
                    drRulX["RuleID"] = strField;
                    if (nodes.Current.MoveToFirstChild())
                    {
                        do
                        {
                            strKey = nodes.Current.GetAttribute("key", string.Empty);
                            strField = nodes.Current.GetAttribute("value", string.Empty);
                            strOperator = nodes.Current.GetAttribute("operator", string.Empty);
                            strDataType = nodes.Current.GetAttribute("datatype", string.Empty);
                            strOutput = nodes.Current.GetAttribute("direction", string.Empty);
                            strIsDerived = nodes.Current.GetAttribute("derived", string.Empty);
                            if (Convert.ToBoolean(nodes.Current.GetAttribute("allownull", string.Empty)))
                            {
                                strIsNullAllowed = ":null";
                            }
                            else
                            {
                                strIsNullAllowed = string.Empty;
                            }
                            

                            //Generating the table column collection
                            if (IsCreateColumn)
                            {
                                dtRulX.Columns.Add(new DataColumn(strKey)); 
                            }

                            sbRowValueList.Append(strField);
                            sbRowValueList.Append(",");

                            drRulX[strKey] = strField;
                            drDataTypeRulX[strKey] = strDataType + " (" + strOutput + ")" + strIsNullAllowed;



                        } while (nodes.Current.MoveToNext());

                        IsCreateColumn = false;
                        
                        
                        
                    }
                    //DataRow dr = new DataRow();
                    
                    //Generating actual records here
                    dtRulX.Rows.Add(drRulX);

                    
                }
                drDataTypeRulX["RuleID"] = "string {None}";
                dtRulX.Rows.InsertAt(drDataTypeRulX, 0);

                return dtRulX;

            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public void GenerateNewRulXData(string rulXFile, Dictionary<string, Dictionary<string,string>> objNewRulXList)
        {

            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(rulXFile);
                //XPathDocument document = new XPathDocument(rulXFile);
                XPathNavigator navigator = xmlDoc.CreateNavigator();

                foreach (KeyValuePair<string, Dictionary<string, string>> keyValRuleID in objNewRulXList)
                {
                    XPathNavigator checkNodesRuleID = navigator.SelectSingleNode("Types/RuleSetClass/RuleSet/Rule[@ID='" + keyValRuleID.Key + "']");
                    if (checkNodesRuleID != null)
                    {
                        MessageBox.Show("RuleID must be Unique, Cannot be Duplicate", "Error Save", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }

                string strDataType = string.Empty;
                string strDataOutput = string.Empty;
                string strFieldValue = string.Empty;
                string strDataTypeAndOuputTypeVal = string.Empty;


                XPathNavigator nodes = navigator.SelectSingleNode("Types/RuleSetClass/RuleSet");

                XmlNode findNewNode = ((System.Xml.IHasXmlNode)nodes).GetNode();

                foreach (KeyValuePair<string, Dictionary<string, string>> keyValItem in objNewRulXList)
                {

                    XmlElement newRule = xmlDoc.CreateElement("Rule");
                    findNewNode.AppendChild(newRule);

                    newRule.SetAttribute("ID", keyValItem.Key);

                
                    Dictionary<string, string> fieldList = new Dictionary<string, string>();
                    fieldList = objNewRulXList[keyValItem.Key];

                    foreach (KeyValuePair<string, string> item in fieldList)
                    {
                        IList<string> objList = item.Value.Split('|');
                        strFieldValue = objList[0];
                        strDataType = objList[1];
                        strDataOutput = objList[2];
                        
                        XmlElement newRuleData = xmlDoc.CreateElement("data");

                        newRuleData.SetAttribute("key", item.Key);
                        newRuleData.SetAttribute("operator", "EQUALS");
                        newRuleData.SetAttribute("datatype", strDataType);
                        newRuleData.SetAttribute("value", strFieldValue);
                        newRuleData.SetAttribute("direction", strDataOutput);
                        newRuleData.SetAttribute("derived", strDataOutput);

                        newRule.AppendChild(newRuleData);
                    } 
                }

                xmlDoc.Save(rulXFile);

            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public bool UpdateRulXData(string rulXFile, string ruleID, string keyField, string newValue)
        {

            try
            {
                
                bool isUpdated = false;
                string strKey = string.Empty;
                string strField = string.Empty;
                string strRuleID = string.Empty;
                Int32 rulXID = Convert.ToInt32(ruleID);

                XmlDocument doc=new XmlDocument();
                doc.Load(rulXFile);
                XPathDocument document = new XPathDocument(rulXFile);
                XPathNavigator navigator = document.CreateNavigator();
                XPathNodeIterator nodes = navigator.Select("Types/RuleSetClass/RuleSet/Rule");

                XmlAttributeCollection objAttCollection = null;
                objAttCollection = doc.DocumentElement.ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[0].Attributes;

                while (nodes.MoveNext())
                {
                    strRuleID = nodes.Current.GetAttribute("ID", string.Empty);
                    if (string.Equals(strRuleID, ruleID))
                    {
                        if (nodes.Current.MoveToFirstChild())
                        {
                            do
                            {
                                strKey = nodes.Current.GetAttribute("key", string.Empty);
                                strField = nodes.Current.GetAttribute("value", string.Empty);

                                //if (nodes.Current is IHasXmlNode)
                                //{
                                    if (string.Equals(strKey, keyField))
                                    {
                                        //nodes.Current.MoveToAttribute("value", string.Empty);
                                        //nodes.Current.SetValue(newValue);
                                        //if (true)
                                        //{
                                        //XmlElement nodeElement = new XmlElement();

                                        //nodeElement = doc.DocumentElement.FirstChild.FirstChild.ChildNodes[rulXID - 1].FirstChild;
                                        //XmlNode findNode = ((System.Xml.IHasXmlNode)nodes.Current).GetNode();
                                        //XmlAttribute attr = findNode.Attributes["value"];

                                        nodes.Current.MoveToAttribute("value",string.Empty);
                                        nodes.Current.SetValue(newValue);
                                        //objAttCollection["value"].Value = newValue; 
                                        //attr.Value = newValue;
                                        //}
                                    } 
                                //}

                            } while (nodes.Current.MoveToNext());

                        } 
                    }
                    
                }

                return isUpdated;

            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public bool UpdateRulXData2(string rulXFile, string ruleID, string keyField, string oldValue, string newValue)
        {
            try
            {
                bool result = true;

                XmlDocument doc;
                System.Xml.XPath.XPathNavigator editor;

                doc = new XmlDocument();
                doc.Load(rulXFile);
                editor = doc.CreateNavigator().SelectSingleNode("/Types/RuleSetClass/RuleSet/Rule[@ID='" + ruleID + "']/data[@key='" + keyField + "' and @value='" + oldValue + "']");
               
                XmlNode findNode = ((System.Xml.IHasXmlNode)editor).GetNode();
                
                XmlAttribute attr = findNode.Attributes["value"];
                attr.Value = newValue;
                doc.Save(rulXFile);

                return result;
            }
            catch (Exception ex)
            {
                
                throw;
            }
        }

        public bool UpdateRulXData3(string rulXFile, List<RulXAttributeObject> objRuleXAttributeList)
        {
            try
            {
                bool result = true;

                XmlDocument doc;
                System.Xml.XPath.XPathNavigator editor;

                doc = new XmlDocument();
                doc.Load(rulXFile);

                foreach (RulXAttributeObject rulXItem in objRuleXAttributeList)
                {
                    editor = doc.CreateNavigator().SelectSingleNode("/Types/RuleSetClass/RuleSet/Rule[@ID='" + rulXItem.RuleID + "']/data[@key='" + rulXItem.KeyField + "' and @value='" + rulXItem.KeyFieldOldValue + "']");

                    if (editor!=null)
                    {
                        XmlNode findNode = ((System.Xml.IHasXmlNode)editor).GetNode();
                        XmlAttribute attr = findNode.Attributes["value"];
                        attr.Value = rulXItem.KeyFieldNewValue;
                    }
                    
                    
                }
                
                doc.Save(rulXFile);

                return result;
            }
            catch (Exception ex)
            {

                throw;
            }
        }

        public bool RemoveRulXData(string rulXFile, List<string> ruleIDList)
        {
            try
            {
                bool result = true;

                XmlDocument doc;
                System.Xml.XPath.XPathNavigator delNodeNav;
                System.Xml.XPath.XPathNavigator parentNodeNav;

                doc = new XmlDocument();
                doc.Load(rulXFile);


                foreach (string ruleID in ruleIDList)
                {
                    delNodeNav = doc.CreateNavigator().SelectSingleNode("/Types/RuleSetClass/RuleSet/Rule[@ID='" + ruleID + "']");
                    parentNodeNav = doc.CreateNavigator().SelectSingleNode("/Types/RuleSetClass/RuleSet");

                    XmlNode findNode = ((System.Xml.IHasXmlNode)delNodeNav).GetNode();
                    XmlNode parentNode = ((System.Xml.IHasXmlNode)parentNodeNav).GetNode();

                    parentNode.RemoveChild(findNode);
                }
                

                doc.Save(rulXFile);

                return result;
            }
            catch (Exception ex)
            {

                throw;
            }
        }
    }
}
